package com.log.enhance.config;

import com.log.enhance.config.properties.EnableFromAndToProperty;
import com.log.enhance.config.properties.LogTraceProperty;
import com.log.enhance.filter.AddTraceIdFilter;
import com.log.enhance.interceptor.FeignRequestInterceptor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;

import static javax.servlet.DispatcherType.REQUEST;

/**
 * 请求traceID相关bean配置类，启动类使用@EnableLogChain注解开启，
 * 可不用@Configuration注解去导入容器了，当然加上也无所谓
 *
 * @author Mr_wenpan@163.com 2021/05/23 22:49
 */
@Slf4j
// @Configuration
@EnableConfigurationProperties(EnableFromAndToProperty.class)
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class EnableLogChainConfiguration {

    private final String banner = " \r\n" +
            " =========================================================================================================================================================                                             _                      _             _        \n" +
            "                                             | |                    | |           (_)       \n" +
            " __      _____ _ __     _ __   __ _ _ __    | | ___   __ _    _ __ | |_   _  __ _ _ _ __   \n" +
            " \\ \\ /\\ / / _ \\ '_ \\   | '_ \\ / _` | '_ \\   | |/ _ \\ / _` |  | '_ \\| | | | |/ _` | | '_ \\  \n" +
            "  \\ V  V /  __/ | | |  | |_) | (_| | | | |  | | (_) | (_| |  | |_) | | |_| | (_| | | | | | \n" +
            "   \\_/\\_/ \\___|_| |_|  | .__/ \\__,_|_| |_|  |_|\\___/ \\__, |  | .__/|_|\\__,_|\\__, |_|_| |_| \n" +
            "                       | |                            __/ |  | |             __/ |         \n" +
            "                       |_|                           |___/   |_|            |___/          " +
            " \r\n" +
            " =========================================================================================================================================================";

    /**
     * 使用springboot的方式添加过滤器（使下面添加的过滤器生效）
     * LogTraceProperty : 当做方法参数，在注入addTraceIdFilterRegistration会去容器中寻找LogTraceProperty
     */
    @Bean
    public FilterRegistrationBean<AddTraceIdFilter> addTraceIdFilterRegistration(LogTraceProperty logTraceProperty,
                                                                                 AddTraceIdFilter addTraceIdFilter) {
        FilterRegistrationBean<AddTraceIdFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        // 设置过滤器
        filterRegistrationBean.setFilter(addTraceIdFilter);
        filterRegistrationBean.setName("addTraceIdFilter");
        filterRegistrationBean.setOrder(Ordered.LOWEST_PRECEDENCE);
        filterRegistrationBean.setDispatcherTypes(REQUEST);
        // 指定需要添加traceId的url路径(即要过滤的路径)，若使用方不在application.yml中指定，则默认拦截所有请求
        filterRegistrationBean.setUrlPatterns(logTraceProperty.getUri());
        return filterRegistrationBean;
    }

    /**
     * prefix = LogTraceProperty.LOG_TRACE_PREFIX：
     * 表示使用配置文件中前缀为plugin.log.trace的属性的值初始化该bean定义产生的的bean实例的同名属性
     * 用法可参考：https://hello.blog.csdn.net/article/details/104575745
     */
    @Bean
    @ConditionalOnMissingBean(LogTraceProperty.class)
    @ConfigurationProperties(prefix = LogTraceProperty.LOG_TRACE_PREFIX)
    public LogTraceProperty logTraceProperty() {
        return new LogTraceProperty();
    }

    /**
     * 给日志里添加traceId的过滤器注入到容器
     */
    @Bean
    public AddTraceIdFilter addTraceIdFilter() {
        // 可百度这里的转义字符
        // 打印日志项目地址\a\u000d log.info(banner);
        return new AddTraceIdFilter();
    }

    /**
     * 开启feign调用日志链路追踪（传递traceId、from、to）
     * 必须要在配置文件中显示配置 plugin.log.trace.enable-feign : true
     */
    @Bean
//    @ConditionalOnProperty(
//            prefix = "plugin.log.trace",
//            name = {"enable-feign"},
//            havingValue = "true"
//    )
    @ConditionalOnMissingBean
    public FeignRequestInterceptor feignRequestInterceptor() {
        return new FeignRequestInterceptor();
    }
}
